#pragma once

#include "Socket.hpp"
#include "Common.hpp"
#include <jsoncpp/json/json.h>
#include <functional>
#include <memory>

class Request
{
public:
    Request()
    {
    }

    Request(int x, int y, char oper)
        : _x(x), _y(y), _oper(oper)
    {
    }

    std::string Serialize()
    {
        // -------------------------- 序列化（生成字符串） --------------------------
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::StreamWriterBuilder writer_builder;
        std::string json_str = Json::writeString(writer_builder, root); // 简洁写法

        return json_str;
    }

    bool Deserialize(std::string &json_str)
    {
        // -------------------------- 反序列化（解析字符串） --------------------------
        Json::Value parsed_root;
        Json::CharReaderBuilder reader_builder;
        std::string err_msg; // 用于存储解析错误信息

        // 创建CharReader并解析字符串
        std::unique_ptr<Json::CharReader> reader(reader_builder.newCharReader());
        bool success = reader->parse(
            json_str.c_str(),                     // 字符串起始地址
            json_str.c_str() + json_str.length(), // 字符串结束地址
            &parsed_root,                         // 解析结果存储到parsed_root
            &err_msg                              // 错误信息存储到err_msg
        );

        if (success)
        {
            _x = parsed_root["x"].asInt();
            _y = parsed_root["y"].asInt();
            _oper = parsed_root["oper"].asInt(); // char通过ASCII映射为整数
        }
        else
        {
            LOG(LogLevel::ERROR) << "\n解析失败! 错误信息: " << err_msg;
        }

        return success;
    }

    int GetX()
    {
        return _x;
    }
    int GetY()
    {
        return _y;
    }
    char GetOper()
    {
        return _oper;
    }

private:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response()
    {
    }

    Response(int result, int code)
        : _result(result), _code(code)
    {
    }

    std::string Serialize()
    {
        // -------------------------- 序列化（生成字符串） --------------------------
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::StreamWriterBuilder writer_builder;
        std::string json_str = Json::writeString(writer_builder, root); // 简洁写法

        return json_str;
    }

    bool Deserialize(std::string &json_str)
    {
        // -------------------------- 反序列化（解析字符串） --------------------------
        Json::Value parsed_root;
        Json::CharReaderBuilder reader_builder;
        std::string err_msg; // 用于存储解析错误信息

        // 创建CharReader并解析字符串
        std::unique_ptr<Json::CharReader> reader(reader_builder.newCharReader());
        bool success = reader->parse(
            json_str.c_str(),                     // 字符串起始地址
            json_str.c_str() + json_str.length(), // 字符串结束地址
            &parsed_root,                         // 解析结果存储到parsed_root
            &err_msg                              // 错误信息存储到err_msg
        );

        if (success)
        {
            _result = parsed_root["result"].asInt();
            _code = parsed_root["code"].asInt();
        }
        else
        {
            LOG(LogLevel::ERROR) << "\n解析失败! 错误信息: " << err_msg;
        }

        return success;
    }

    void ShowResult()
    {
        std::cout << "result is: " << _result << '[' << _code << ']' << std::endl;
    }

    void SetResult(int result)
    {
        _result = result;
    }

    void SetCode(int code)
    {
        _code = code;
    }

private:
    int _result;
    int _code; // 0为正确，非0为各种错误
};

const static std::string sep = "\r\n";
using func_t = std::function<Response(Request &req)>;

class Protocol
{
public:
    Protocol()
    {
    }

    Protocol(func_t func)
        : _func(func)
    {
    }

    std::string Encode(const std::string &json_str)
    {
        // TCP是面向字节流的，要读到一个完整的json串，需要做些标记
        // 这里使用格式：json串长度+\r\n+json串+\r\n,即"json串长度\r\njson串\r\n"
        int len = json_str.size();

        return std::to_string(len) + sep + json_str + sep;
    }

    bool Decode(std::string &buffer, std::string *package)
    {
        int pos = buffer.find("\r\n");
        if (pos == std::string::npos)
            return false;

        int str_len = std::stoi(buffer.substr(0, pos));
        int json_str_len = pos + sep.size() + str_len + sep.size();
        if (buffer.size() < json_str_len)
            return false;

        *package = buffer.substr(pos + sep.size(), str_len);
        buffer.erase(0, json_str_len);
        return true;
    }

    void GetRequest(std::shared_ptr<Socket> &sockfd, const InetAddr &client)
    {
        std::string buffer;

        while (true)
        {
            int n = sockfd->Recv(&buffer);

            if (n > 0)
            {
                std::string json_package;

                // 1. 解析报文，不完整，继续读(所以在Recv里面是+=)
                while (Decode(buffer, &json_package))
                {
                    // 2. 反序列化
                    Request req;
                    bool OK = req.Deserialize(json_package);
                    if (!OK)
                        continue; // 跳过当前无效的报文，继续处理后续可能有效的报文，防止buffer累积

                    // 3. 执行函数
                    Response resp = _func(req);

                    // 4. 序列化
                    std::string json_str = resp.Serialize();

                    // 5. Encode,加报头
                    std::string send_str = Encode(json_str);

                    // 6. 发送
                    sockfd->Send(send_str);
                }
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << client.StringAddr() << " 退出了!";
                sockfd->Close();
                break;
            }
            else // n < 0
            {
                LOG(LogLevel::WARNING) << client.StringAddr() << " 异常";
                sockfd->Close();
                break;
            }
        }
    }

    bool GetResponse(std::shared_ptr<Socket> &client, Response *resp)
    {
        std::string buffer;

        while (true)
        {
            int n = client->Recv(&buffer);

            if (n > 0)
            {
                std::string json_package;

                // 1. 解析报文，不完整，继续读(所以在Recv里面是+=)
                if (Decode(buffer, &json_package))
                {
                    // 2. 反序列化
                    return resp->Deserialize(json_package); // 只读取一次完整的报文
                }
            }
            else if (n == 0)
            {
                std::cout << "server quit" << std::endl;
                return false;
            }
            else // n < 0
            {
                std::cout << "server error" << std::endl;
                return false;
            }
        }
    }

    std::string BuildRequestString(int x, int y, char oper)
    {
        Request req(x, y, oper);

        // 1. 序列化
        std::string json_str = req.Serialize();

        // 2. Encode.加报头
        return Encode(json_str);
    }

private:
    func_t _func;
};